home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
kernel
/
dev
/
ds5000.md
/
devSmem.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-18
|
13KB
|
420 lines
/*
* devSmem.c --
*
* Stubs to implement /dev/smem. Allow reading and writing
* to kernel memory.
*
*
* Copyright 1987 Regents of the University of California
* All rights reserved.
*/
#ifndef lint
static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/ds5000.md/devSmem.c,v 1.1 92/08/13 15:53:37 secor Exp $ SPRITE (Berkeley)";
#endif not lint
#include "sprite.h"
#include "fs.h"
#include <vmPmaxConst.h>
#include <dbg.h>
#define NOGAP
static char smemBuf[1024];
extern int vm_PageSize;
extern int mach_KernStackSize;
extern int vmBlockCacheEndAddr;
extern int vmBlockCacheBaseAddr;
extern int vmStackEndAddr;
extern int vmStackBaseAddr;
extern int vmMemEnd;
extern int vmBootEnd;
extern int mach_KernStart;
extern int mach_CodeStart;
extern Mach_DebugState mach_DebugState;
static void DebugToRegState _ARGS_((Mach_DebugState *debugPtr,
Mach_RegState *regPtr));
/*
*----------------------------------------------------------------------
*
* Dev_SmemRead --
*
* Return number of bytes read and SUCCESS if nonzero bytes returned.
*
* Results:
* A standard Sprite return status.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
/*ARGSUSED*/
ReturnStatus
Dev_SmemRead(devicePtr, readPtr, replyPtr)
Fs_Device *devicePtr;
Fs_IOParam *readPtr; /* Read parameter block */
Fs_IOReply *replyPtr; /* Return length and signal */
{
int status, bytesLeft;
int kernelAddress;
int numPages, bytesInPage;
char *bufPtr;
StopInfo stopInfo;
Dbg_DumpBounds currentBounds;
stopInfo.codeStart = (int)mach_CodeStart;
stopInfo.trapType = (mach_DebugState.causeReg & MACH_CR_EXC_CODE) >>
MACH_CR_EXC_CODE_SHIFT;
DebugToRegState(&mach_DebugState, &(stopInfo.regs));
currentBounds.pageSize = vm_PageSize;
currentBounds.stackSize = mach_KernStackSize;
currentBounds.kernelCodeStart = (unsigned int) mach_KernStart;
currentBounds.kernelCodeSize =
(unsigned int) (vmBootEnd - mach_KernStart);
currentBounds.kernelDataStart = VMMACH_VIRT_CACHED_START;
currentBounds.kernelDataSize = (unsigned int)
(vmMemEnd - VMMACH_VIRT_CACHED_START);
currentBounds.kernelStacksStart = (unsigned int)vmStackBaseAddr;
currentBounds.kernelStacksSize = (unsigned int)
(vmStackEndAddr - vmStackBaseAddr);
currentBounds.fileCacheStart = (unsigned int)vmBlockCacheBaseAddr;
currentBounds.fileCacheSize = (unsigned int) (vmBlockCacheEndAddr -
vmBlockCacheBaseAddr);
kernelAddress = readPtr->offset;
bytesLeft = readPtr->length;
bufPtr = readPtr->buffer;
if (kernelAddress < sizeof(StopInfo)) {
if (bytesLeft + kernelAddress <= sizeof(StopInfo)) {
bcopy(((char *)&stopInfo) + kernelAddress, readPtr->buffer, readPtr->length);
replyPtr->length = readPtr->length;
return(SUCCESS);
}
bcopy(((char *)&stopInfo) + kernelAddress, readPtr->buffer, sizeof(StopInfo) - kernelAddress);
bytesLeft -= sizeof(StopInfo) - kernelAddress;
bufPtr += sizeof(StopInfo) - kernelAddress;
kernelAddress = sizeof(StopInfo);
}
if (kernelAddress < (sizeof(StopInfo) + sizeof(Dbg_DumpBounds))) {
if (bytesLeft + kernelAddress <= sizeof(StopInfo) + sizeof(Dbg_DumpBounds)) {
bcopy(((char *)¤tBounds) + sizeof(StopInfo) - kernelAddress, bufPtr, bytesLeft);
replyPtr->length = readPtr->length;
return(SUCCESS);
}
bcopy(((char *)¤tBounds) + sizeof(StopInfo) - kernelAddress, bufPtr, sizeof(Dbg_DumpBounds));
bytesLeft -= sizeof(StopInfo) + sizeof(Dbg_DumpBounds) - kernelAddress;
bufPtr += sizeof(StopInfo) + sizeof(Dbg_DumpBounds) - kernelAddress;
kernelAddress = mach_KernStart;
}
kernelAddress += mach_KernStart - (sizeof(StopInfo) + sizeof(Dbg_DumpBounds));
#ifdef NOGAP
if (kernelAddress > vmBootEnd) {
kernelAddress += VMMACH_VIRT_CACHED_START - vmBootEnd;
}
if (kernelAddress > vmMemEnd) {
kernelAddress += vmStackBaseAddr - vmMemEnd;
}
if (kernelAddress > vmStackEndAddr) {
kernelAddress += vmBlockCacheBaseAddr - vmStackEndAddr;
}
if (kernelAddress > vmBlockCacheEndAddr) {
return (SYS_INVALID_ARG);
}
#else
if (kernelAddress > vmBootEnd &&
kernelAddress < VMMACH_VIRT_CACHED_START) {
return(SYS_INVALID_ARG);
}
if (kernelAddress > vmMemEnd &&
kernelAddress < vmStackBaseAddr) {
return(SYS_INVALID_ARG);
}
if (kernelAddress > vmStackEndAddr &&
kernelAddress < vmBlockCacheBaseAddr) {
return(SYS_INVALID_ARG);
}
if (kernelAddress > vmBlockCacheEndAddr) {
return(SYS_INVALID_ARG);
}
#endif
numPages = ((kernelAddress + bytesLeft - 1) >> VMMACH_PAGE_SHIFT) -
(kernelAddress >> VMMACH_PAGE_SHIFT);
if (!Dbg_InRange(kernelAddress, bytesLeft, FALSE)) {
replyPtr->length = 0;
return(SYS_ARG_NOACCESS);
}
bytesInPage = vm_PageSize - (kernelAddress & (vm_PageSize-1));
if (bytesLeft < bytesInPage) {
bcopy(kernelAddress, bufPtr, bytesLeft);
replyPtr->length = readPtr->length;
return(SUCCESS);
}
bcopy(kernelAddress, bufPtr, bytesInPage);
bytesLeft -= bytesInPage;
bufPtr += vm_PageSize;
while (numPages > 0) {
if (!Dbg_InRange(kernelAddress, bytesLeft, FALSE)) {
replyPtr->length = 0;
return(SYS_ARG_NOACCESS);
}
if (bytesLeft < vm_PageSize) {
bcopy(kernelAddress, bufPtr, bytesLeft);
replyPtr->length = readPtr->length;
return(SUCCESS);
}
bcopy(kernelAddress, bufPtr, vm_PageSize);
bytesLeft -= vm_PageSize;
bufPtr += vm_PageSize;
numPages--;
}
replyPtr->length = readPtr->length;
return(SUCCESS);
}
/*
*----------------------------------------------------------------------
*
* Dev_SmemWrite --
*
* Writes if it can, and returns SUCCESS if it wrote.
*
* Results:
* A standard Sprite return status.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
/*ARGSUSED*/
ReturnStatus
Dev_SmemWrite(devicePtr, writePtr, replyPtr)
Fs_Device *devicePtr;
Fs_IOParam *writePtr; /* Standard write parameter block */
Fs_IOReply *replyPtr; /* Return length and signal */
{
int status, bytesLeft;
int kernelAddress;
int numPages, bytesInPage;
char *bufPtr;
StopInfo stopInfo;
Dbg_DumpBounds currentBounds;
stopInfo.codeStart = (int)mach_CodeStart;
stopInfo.trapType = (mach_DebugState.causeReg & MACH_CR_EXC_CODE) >>
MACH_CR_EXC_CODE_SHIFT;
DebugToRegState(&mach_DebugState, &(stopInfo.regs));
currentBounds.pageSize = vm_PageSize;
currentBounds.stackSize = mach_KernStackSize;
currentBounds.kernelCodeStart = (unsigned int) mach_KernStart;
currentBounds.kernelCodeSize =
(unsigned int) (vmBootEnd - mach_KernStart);
currentBounds.kernelDataStart = VMMACH_VIRT_CACHED_START;
currentBounds.kernelDataSize = (unsigned int)
(vmMemEnd - VMMACH_VIRT_CACHED_START);
currentBounds.kernelStacksStart = (unsigned int)vmStackBaseAddr;
currentBounds.kernelStacksSize = (unsigned int)
(vmStackEndAddr - vmStackBaseAddr);
currentBounds.fileCacheStart = (unsigned int)vmBlockCacheBaseAddr;
currentBounds.fileCacheSize = (unsigned int) (vmBlockCacheEndAddr -
vmBlockCacheBaseAddr);
kernelAddress = writePtr->offset;
bytesLeft = writePtr->length;
bufPtr = writePtr->buffer;
/* Get part or all of stop info if requested. */
if (kernelAddress < sizeof(StopInfo)) {
if (bytesLeft + kernelAddress <= sizeof(StopInfo)) {
bcopy(writePtr->buffer, ((char *)&stopInfo) + kernelAddress, writePtr->length);
replyPtr->length = writePtr->length;
return(SUCCESS);
}
bcopy(writePtr->buffer, ((char *)&stopInfo) + kernelAddress, sizeof(StopInfo) - kernelAddress);
bytesLeft -= sizeof(StopInfo) - kernelAddress;
bufPtr += sizeof(StopInfo) - kernelAddress;
kernelAddress = sizeof(StopInfo);
}
/* Get part or all of dump bounds if requested. */
if (kernelAddress < (sizeof(StopInfo) + sizeof(Dbg_DumpBounds))) {
if (bytesLeft + kernelAddress <= sizeof(StopInfo) + sizeof(Dbg_DumpBounds)) {
bcopy(bufPtr, ((char *)¤tBounds) + sizeof(StopInfo) - kernelAddress, bytesLeft);
replyPtr->length = writePtr->length;
return(SUCCESS);
}
bcopy(bufPtr, ((char *)¤tBounds) + sizeof(StopInfo) - kernelAddress, sizeof(Dbg_DumpBounds));
bytesLeft -= sizeof(StopInfo) + sizeof(Dbg_DumpBounds) - kernelAddress;
bufPtr += sizeof(StopInfo) + sizeof(Dbg_DumpBounds) - kernelAddress;
kernelAddress = sizeof(StopInfo) + sizeof(Dbg_DumpBounds);
}
/* Set address to beginning of kernel memory. */
kernelAddress += mach_KernStart - (sizeof(StopInfo) + sizeof(Dbg_DumpBounds));
/* Make sure offset is valid. */
#ifdef NOGAP
if (kernelAddress > vmBootEnd) {
kernelAddress += VMMACH_VIRT_CACHED_START - vmBootEnd;
}
if (kernelAddress > vmMemEnd) {
kernelAddress += vmStackBaseAddr - vmMemEnd;
}
if (kernelAddress > vmStackEndAddr) {
kernelAddress += vmBlockCacheBaseAddr - vmStackEndAddr;
}
if (kernelAddress > vmBlockCacheEndAddr) {
return (SYS_INVALID_ARG);
}
#else
if (kernelAddress > vmBootEnd &&
kernelAddress < VMMACH_VIRT_CACHED_START) {
return(SYS_INVALID_ARG);
}n
if (kernelAddress > vmMemEnd &&
kernelAddress < vmStackBaseAddr) {
return(SYS_INVALID_ARG);
}
if (kernelAddress > vmStackEndAddr &&
kernelAddress < vmBlockCacheBaseAddr) {
return(SYS_INVALID_ARG);
}
if (kernelAddress > vmBlockCacheEndAddr) {
return(SYS_INVALID_ARG);
}
#endif
/* Find number of pages that request spans. */
numPages = ((kernelAddress + bytesLeft - 1) >> VMMACH_PAGE_SHIFT) -
(kernelAddress >> VMMACH_PAGE_SHIFT);
if (!Dbg_InRange(kernelAddress, bytesLeft, FALSE)) {
replyPtr->length = 0;
return(SYS_ARG_NOACCESS);
}
bytesInPage = vm_PageSize - (kernelAddress & (vm_PageSize-1));
if (bytesLeft < bytesInPage) {
bcopy(bufPtr, kernelAddress, bytesLeft);
replyPtr->length = writePtr->length;
return(SUCCESS);
}
bcopy(bufPtr, kernelAddress, bytesInPage);
bytesLeft -= bytesInPage;
bufPtr += vm_PageSize;
/* Make each page accessible, if possible and copy it into
return buffer. */
while (numPages > 0) {
if (!Dbg_InRange(kernelAddress, bytesLeft, FALSE)) {
replyPtr->length = 0;
return(SYS_ARG_NOACCESS);
}
if (bytesLeft < vm_PageSize) {
bcopy(bufPtr, kernelAddress, bytesLeft);
replyPtr->length = writePtr->length;
return(SUCCESS);
}
bcopy(bufPtr, kernelAddress, vm_PageSize);
bytesLeft -= vm_PageSize;
bufPtr += vm_PageSize;
numPages--;
}
replyPtr->length = writePtr->length;
return(SUCCESS);
}
/*
*----------------------------------------------------------------------
*
* Dev_SmemIOControl --
*
* This procedure handles IOControls for /dev/smem and other
* devices. It refuses all IOControls except for a few of
* the generic ones, for which it does nothing.
*
* Results:
* A standard Sprite return status.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
ReturnStatus
Dev_SmemIOControl(devicePtr, ioctlPtr, replyPtr)
Fs_Device *devicePtr;
Fs_IOCParam *ioctlPtr;
Fs_IOReply *replyPtr;
{
if ((ioctlPtr->command == IOC_GET_FLAGS)
|| (ioctlPtr->command == IOC_SET_FLAGS)
|| (ioctlPtr->command == IOC_SET_BITS)
|| (ioctlPtr->command == IOC_CLEAR_BITS)
|| (ioctlPtr->command == IOC_REPOSITION)) {
return SUCCESS;
}
return GEN_NOT_IMPLEMENTED;
}
/*
*----------------------------------------------------------------------
*
* Dev_SmemSelect --
*
* This procedure handles selects for /dev/smem and other
* devices that are always ready.
*
* Results:
* The device is indicated to be readable and writable.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
ReturnStatus
Dev_SmemSelect(devicePtr, readPtr, writePtr, exceptPtr)
Fs_Device *devicePtr; /* Ignored. */
int *readPtr; /* Read bit to clear if not readable */
int *writePtr; /* Write bit to clear if not readable */
int *exceptPtr; /* Except bit to clear if not readable */
{
*exceptPtr = 0;
return(SUCCESS);
}
/*
*----------------------------------------------------------------------
*
* DebugToRegState --
*
* Converts a Mach_DebugState to Mach_RegState.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static void
DebugToRegState(debugPtr, regPtr)
Mach_DebugState *debugPtr;
Mach_RegState *regPtr;
{
regPtr->pc = (Address) debugPtr->excPC;
bcopy((char *) debugPtr->regs, (char *) regPtr->regs,
MACH_NUM_GPRS * sizeof(int));
bcopy((char *) debugPtr->fpRegs, (char *) regPtr->fpRegs,
MACH_NUM_FPRS * sizeof(int));
regPtr->fpStatusReg = debugPtr->fpCSR;
regPtr->mfhi = debugPtr->multHi;
regPtr->mflo = debugPtr->multLo;
}